﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleRayTracer
{
    class Triangle : Object3D
    {
        private Vector3D vert1;
        private Vector3D vert2;
        private Vector3D vert3;
        private bool culling;

        private const double EPSILON = 0.000001; 

        public Triangle(Vector3D vertex1, Vector3D vertex2, Vector3D vertex3, double colourRed, double colourGreen, double colourBlue)
        {
            vert1 = vertex1;
            vert2 = vertex2;
            vert3 = vertex3;

            clR = colourRed;
            clG = colourGreen;
            clB = colourBlue;

            culling = false;
        }

        public Triangle(Vector3D vertex1, Vector3D vertex2, Vector3D vertex3, double colourRed, double colourGreen, double colourBlue, bool cullingEnable)
        {
            vert1 = vertex1;
            vert2 = vertex2;
            vert3 = vertex3;

            clR = colourRed;
            clG = colourGreen;
            clB = colourBlue;

            culling = cullingEnable;
        }

        public override bool IsIntersect(Ray ray)
        {
            return true;
        }

        public override bool GetIntersect(Ray ray, ref double distance)
        {
            Vector3D triEdge1;
            Vector3D triEdge2;
            Vector3D q;
            double det;

            triEdge1 = vert2 - vert1;
            triEdge2 = vert3 - vert1;

            q = Vector3D.Cross(ray.direction, triEdge2);
            det = Vector3D.Dot(triEdge1, q);

            if (culling)
            {
                if (det < EPSILON)
                {
                    distance = 0.0;
                    return false;
                }


            }
            else
            {
                if ((det > -EPSILON) && (det < EPSILON))
                {
                    distance = 0.0;
                    return false;
                }

                double invDet = 1.0 / det;

                Vector3D s = ray.origin - vert1;

                double u = Vector3D.Dot(s, q) * invDet;

                if ((u < 0.0) || (u > 1.0))
                {
                    distance = 0.0;
                    return false;
                }

                Vector3D r = Vector3D.Cross(s, triEdge1);

                double v = Vector3D.Dot(ray.direction, r) * invDet;

                if ((v < 0.0) || ((u + v) > 1.0))
                {
                    distance = 0.0;
                    return false;
                }

                double t = Vector3D.Dot(triEdge2, r) * invDet;
                distance = t;
            }

            return true;
        }

        public override Vector3D GetNormal(Vector3D point)
        {
            throw new NotImplementedException();
        }

        public override void Move(Vector3D trans, Vector3D centre)
        {
            throw new NotImplementedException();
        }

        public override void MoveTo(Vector3D dest, Vector3D centre)
        {
            throw new NotImplementedException();
        }

        public override void RotX(double angle, Vector3D centre)
        {
            throw new NotImplementedException();
        }

        public override void RotY(double angle, Vector3D centre)
        {
            throw new NotImplementedException();
        }

        public override void RotZ(double angle, Vector3D centre)
        {
            throw new NotImplementedException();
        }
    }
}
